﻿using Leo.Common.MQ;
using Leo.MSATracert;
using RabbitMQ.Client;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Text;

namespace Leo.Common.RabbitMQ
{
    
    public class RabbitProducer : IRabbitProducer, IMQProducer
    { 
        protected readonly RabbitConnection connection;

        private readonly RabbitConfig config;

        private readonly ConcurrentDictionary<string, IModel> channelPool = new ConcurrentDictionary<string, IModel>();

        public MessageQueueType QueueType
        {
            get
            {
                return MessageQueueType.RabbitMQ;
            }
        }

        public RabbitProducer(RabbitConnection connection)
        {
            this.connection = connection;
            this.config = connection.config;
        }

        public Task<bool> ProduceAsync(IMessageModel message)
        {
            string destination = message.GetDestination();
            PublicationAddress address = this.GetAddress(destination);
            object obj = this.config.AssignIndependentChannelToEachProducer ? this.channelPool.GetOrAdd(address.ExchangeName, (string key) => this.connection.CreateNewChannel()) : this.connection.GetChannel();
           
            string messageJson = message.GetMessageJson();
            object obj2 = obj;
            IBasicProperties basicProperties = RabbitProducer.BuildMessageProperties(obj2, address, message);

            byte[] bytes = Encoding.UTF8.GetBytes(messageJson);

            IModelExensions.BasicPublish(obj2, address, basicProperties, bytes);
            return Task.FromResult<bool>(true);
        }

        private static IBasicProperties BuildMessageProperties(IModel channel, PublicationAddress addr, IMessageModel message)
        {
            IBasicProperties basicProperties = channel.CreateBasicProperties();
            basicProperties.DeliveryMode = 2;
            string messageType = message.GetMessageType();
            if (!string.IsNullOrEmpty(messageType))
            {
                basicProperties.Type = messageType;
            }
            IBasicProperties basicProperties2 = basicProperties;
            if (basicProperties2.Headers == null)
            {
                basicProperties2.Headers = new Dictionary<string, object>();
            }
            basicProperties.Headers.Add("traceId", ServiceInvocationLinkTrace.GetPrincipal(null, null).RequestId);
            MessageProperty properties = message.GetProperties();
            if (properties == null)
            {
                return basicProperties;
            }
            if (properties.TimeoutSeconds > 0L)
            {
                long num = properties.TimeoutSeconds * 1000L;
                if (num >= (long)((ulong)-1))
                {
                    num = (long)((ulong)-1001);
                }
                if (ExchangeWorkMode.Delayed.ToString().Equals(addr.ExchangeType, StringComparison.OrdinalIgnoreCase))
                {
                    basicProperties.Headers.Add("x-delay", num);
                }
                else
                {
                    basicProperties.Expiration = num.ToString();
                }
            }
            if (properties.DeliveryMode > 0)
            {
                basicProperties.DeliveryMode = properties.DeliveryMode;
            }
            if (!string.IsNullOrEmpty(properties.CorrelationId))
            {
                basicProperties.CorrelationId = properties.CorrelationId;
            }
            return basicProperties;
        }

        protected PublicationAddress GetAddress(string desctination)
        {
            PublicationAddress result;
            if (!PublicationAddress.TryParse(desctination, ref result))
            {
                throw new ArgumentException("消息发送目的地不正确");
            }
            return result;
        }

        public async Task<bool> ProduceAsync<T>(T data, string destination)
        {
            // 实现序列化和发送逻辑
            // 示例伪代码：
            var message = new JsonMessageModel<T>(data);
            return await ProduceAsync(message);
        }

        public async Task<bool> ProduceAsync<T>(T data, string destination, MessageProperty property)
        {
            // 带自定义属性的发送逻辑
            var message = new CustomPropertyMessageModel<T>(data, property);
            return await ProduceAsync(message);
        }

    }
}
